﻿using Minecraft.BLL;
using Minecraft.BLL.mysql;
using Minecraft.Config;
using Minecraft.Config.Csv.CsvCls;
using Minecraft.Config.Csv.CsvCom;
using Minecraft.Config.ipConst;
using Minecraft.Model;
using Minecraft.Model.Backpack;
using Minecraft.Model.ReqResp;
using SuperSocket.SocketBase.Command;
using SuperSocket.SocketBase.Protocol;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Minecraft.ServerHall.Cmd
{
	public class BackpackTakeGoods : CommandBase<MinecraftSession, StringRequestInfo>
	{
		public override string Name
		{
			get
			{
				return ProtocolHelper.GetProtocolStr(defCommand);
			}
		}
		private EnumCommand defCommand = EnumCommand.Backpack_BackpackTakeGoods;
		public override void ExecuteCommand(MinecraftSession session, StringRequestInfo requestInfo)
		{
			var req = requestInfo.GetRequestObj<BackpackTakeGoodsReq>(session);
			if (req == null)
			{
				session.Send(defCommand, req, new BaseResp { RespLevel = RespLevelEnum.Error, Msg = $"错误1：（原因：请求实体为空）" });
				return;
			}
			if (!session.minecraftSessionInfo.IsLogin)
			{
				session.Send(defCommand, req, new BaseResp { RespLevel = RespLevelEnum.Error, Msg = $"错误1：（原因：未登录）" });
				return;
			}
			//if (JsonConfig.Value.IsDebug)
			//{
			//	req = new BackpackTakeGoodsReq
			//	{
			//		enumFurnitureType = EnumFurnitureType.Storage,
			//		furnitureId = session.minecraftSessionInfo.furnitureStorageList.FirstOrDefault().FurnitureId
			//	};
			//}
			var map = session.minecraftSessionInfo.map;
			if (map.isMoving_Convert)
			{
				session.Send(defCommand, req, new BaseResp { RespLevel = RespLevelEnum.Error, Msg = "错误1：（原因：正处于大地图界面的移动状态，不能调用此接口）" });
				return;
			}

			var timeNow = DateTimeOffset.Now;
			List<EnumGoodsBelongsToType> lista = new List<EnumGoodsBelongsToType>()
			{
				EnumGoodsBelongsToType.FurnitureStorage,
				EnumGoodsBelongsToType.Treasurebox,
				EnumGoodsBelongsToType.PlayerCorpse,
				EnumGoodsBelongsToType.MonsterCorpseAndDismantleFurniture,
			};
			if (!lista.Any(m => m == req.enumGoodsBelongsToType))
			{
				session.Send(defCommand, req, new BaseResp { RespLevel = RespLevelEnum.Error, Msg = $"错误1：（原因：目前暂不支持当前物品所属类型的全部物品拿走操作【{req.enumGoodsBelongsToType.ToString()}】）" });
				return;
			}

			if (req.guid.IsNullOrWhiteSpace())
			{
				req.guid = "";
			}
			Point3 point3 = null;
			switch (req.enumGoodsBelongsToType)
			{
				case EnumGoodsBelongsToType.FurnitureStorage:
					{
						//家具信息
						var furniture = session.minecraftSessionInfo.furnitureStorageList.FirstOrDefault(m => m.FurnitureId == req.guid);
						if (furniture == null)
						{
							session.Send(defCommand, req, new BaseResp { RespLevel = RespLevelEnum.Error, Msg = "错误3：（原因：该存储家具信息不存在）" });
							return;
						}
						req.guid = furniture.FurnitureId;
						point3 = furniture.point3;
					}
					break;
				case EnumGoodsBelongsToType.Treasurebox:
					{
						//家具信息
						var furniture = session.minecraftSessionInfo.furnitureTreasureBoxList.FirstOrDefault(m => m.FurnitureId == req.guid);
						if (furniture == null)
						{
							session.Send(defCommand, req, new BaseResp { RespLevel = RespLevelEnum.Error, Msg = "错误3：（原因：该宝箱信息不存在）" });
							return;
						}
						req.guid = furniture.FurnitureId;
						point3 = furniture.point3;
					}
					break;
				case EnumGoodsBelongsToType.PlayerCorpse:
					{
						//时间超时验证
						var timeSpanSeconds = Convert.ToInt32((timeNow - session.minecraftSessionInfo.player.LastDeathTime).TotalSeconds);
						if (timeSpanSeconds > MinecraftConfig.CorpseDurationSeconds)
						{
							session.Send(defCommand, req, new BaseResp { RespLevel = RespLevelEnum.Error, Msg = "错误3：（原因：尸体超时）" });
							return;
						}
					}
					break;
				case EnumGoodsBelongsToType.MonsterCorpseAndDismantleFurniture:
					{
						//合法性验证
						var dropInfo = session.minecraftSessionInfo.dropinfoList.FirstOrDefault(m => m.DropId.ToString() == req.guid);
						if (dropInfo == null)
						{
							session.Send(defCommand, req, new BaseResp { RespLevel = RespLevelEnum.Error, Msg = "错误3：（原因：dropInfo 不存在）" });
							return;
						}
						if (dropInfo.MapId != map.SourceMapId)
						{
							session.Send(defCommand, req, new BaseResp { RespLevel = RespLevelEnum.Error, Msg = "错误3：（原因：dropInfo.MapId != map.SourceMapId）" });
							return;
						}
						//超时验证
						var seconds = Convert.ToInt32((timeNow - dropInfo.DropTime).TotalSeconds);
						if (seconds > MinecraftConfig.DismantleFurnitureBackpackSeconds)
						{
							session.Send(defCommand, req, new BaseResp { RespLevel = RespLevelEnum.Error, Msg = "错误3：（原因：已经超时）" });
							return;
						}
					}
					break;
				default:
					{
						session.Send(defCommand, req, new BaseResp { RespLevel = RespLevelEnum.Error, Msg = $"错误3：（原因：不支持【{req.enumGoodsBelongsToType.ToString()}】）" });
						return;
					}
					break;
			}

			//判断存储家具/宝箱中还有没有物品
			//存储家具中的所有物品
			Func<GoodsModel, bool> predicateStorage = m => m.enumGoodsBelongsToType_Convert == req.enumGoodsBelongsToType && m.guid == req.guid;
			var furnitureGoodsList = session.minecraftSessionInfo.goodsList.Where(predicateStorage).GetBackpackGoodsCellInfo();
			if (furnitureGoodsList == null || !furnitureGoodsList.Any())
			{
				session.Send(defCommand, req, new BaseResp { RespLevel = RespLevelEnum.Error, Msg = "错误3：（原因：存储家具/宝箱中没有物品了）" });
				return;
			}

			//添加操作影响的positionOptList
			List<BackpackGoodsPositionOpt> positionOptList = new List<BackpackGoodsPositionOpt>();

			//转移到背包的物品列表
			List<GoodsModel> goodsModelList = new List<GoodsModel>();
			TakeGoods(session, defCommand, req.guid, req.enumGoodsBelongsToType, positionOptList, goodsModelList, out BaseResp baseResp);
			if (baseResp.RespLevel != RespLevelEnum.Success)
			{
				session.Send(defCommand, req, baseResp);
				return;
			}

			if (positionOptList == null || !positionOptList.Any())
			{
				session.Send(defCommand, req, new BaseResp { RespLevel = RespLevelEnum.Error, Msg = "错误3：（原因：背包已经满了）" });
				return;
			}

			//找到受影响的物品位置信息
			Func<GoodsModel, bool> predicateBeAffected = m =>
				(positionOptList.Any(n => n.enumGoodsBelongsToType == m.enumGoodsBelongsToType_Convert
				&& n.GoodsPosition == m.GoodsPosition && n.guid == m.guid));
			var posGoodsinfoList = session.minecraftSessionInfo.goodsList.Where(predicateBeAffected).GetBackpackGoodsCellInfo();

			var posGoodsinfoOptList = posGoodsinfoList.Select(m => new BackpackGoodsPositionOpt()
			{
				enumGoodsBelongsToType = m.enumGoodsBelongsToType,
				GoodsPosition = m.GoodsPosition,
				guid = m.guid,
			}).ToList();

			////算存储家具由于上面的操作影响而导致空缺的位置（求差集）
			//var exceptList = positionOptList.Except(posGoodsinfoOptList).ToList();
			////补上差集
			//posGoodsinfoList.AddRange(exceptList.Select(m => new BackpackCellInfo()
			//{
			//	enumGoodsBelongsToType = m.enumGoodsBelongsToType,
			//	GoodsItemId = "",
			//	//GoodsList = new List<BackpackGoodsInfo>(),
			//	GodsId = "",
			//	Num = 0,
			//	GoodsPosition = m.GoodsPosition,
			//	guid = m.guid,
			//	WastageValue = 0
			//}).ToList());

			//var storageGoodsinfoList = posGoodsinfoList.Where(m => m.enumGoodsBelongsToType == enumGoodsBelongsToType).ToList();

			session.minecraftSessionInfo.goodsList.RemoveAll(m => m.Num <= 0);

			var resp = new BackpackTakeGoodsResp
			{
				enumGoodsBelongsToType = req.enumGoodsBelongsToType,
				guid = req.guid,
				//transfertoBpGoodsinfoList = transfertoBpGoodsinfoList,
				//storageGoodsinfoList = storageGoodsinfoList
				posGoodsinfoList = posGoodsinfoList,
				furniturePoint3 = point3,
				playerCorpseId = req.playerCorpseId,
				entityId = req.entityId
			};
			session.Send(defCommand, req, resp);
		}


		private static void TakeGoods(MinecraftSession session, EnumCommand defCommand, string guid,
			EnumGoodsBelongsToType enumGoodsBelongsToType,
			List<BackpackGoodsPositionOpt> positionOptList, List<GoodsModel> goodsModelList, out BaseResp baseResp, List<int> posList = default(List<int>))
		{
			if (posList == null)
			{
				posList = new List<int>();
			}
			//跳出循环条件：得到错误消息，或者背包已经满了，或者存储家具没有物品了
			session.IsBackpackFull(out baseResp, out bool isFull, out List<BackpackGoodsItemInfo> canPlacedBpCellInfoList);
			if (baseResp.RespLevel != RespLevelEnum.Success)
			{
				return;
			}
			if (isFull) //背包已经满了
			{
				return;
			}
			Func<GoodsModel, bool> predicateStorage = m => m.enumGoodsBelongsToType_Convert == enumGoodsBelongsToType && m.Num > 0 && m.guid == guid;
			var furnitureCellGoodsInfo = session.minecraftSessionInfo.goodsList.Where(predicateStorage).FirstOrDefault(m => !posList.Any(p => p == m.GoodsPosition));
			if (furnitureCellGoodsInfo != null)
			{
				//优先堆叠，再填空缺
				var bpGoodsItemInfo = canPlacedBpCellInfoList.FirstOrDefault(m => m.GoodsItemId == furnitureCellGoodsInfo.GoodsItemId);
				if (bpGoodsItemInfo == null)
				{
					bpGoodsItemInfo = canPlacedBpCellInfoList.FirstOrDefault(m => m.GoodsNum <= 0);
					if (bpGoodsItemInfo != null)
					{
						bpGoodsItemInfo.GoodsItemId = furnitureCellGoodsInfo.GoodsItemId;
					}
				}
				//判断是否可以移动
				if (bpGoodsItemInfo != null)
				{
					//获取移动背包中的指定类型物品的个数的最大值
					var maxCellNumCount = session.GetMaxCellNumConvert(furnitureCellGoodsInfo.GoodsItemId);

					//物品移动操作
					//背包中的指定格子还可以容纳多少个物品
					var canMoveCount = maxCellNumCount - bpGoodsItemInfo.GoodsNum;
					//得到实际可以移动的个数
					canMoveCount = Math.Min(canMoveCount, furnitureCellGoodsInfo.Num);

					bpGoodsItemInfo.GoodsNum += canMoveCount;

					var goodsInfo = session.minecraftSessionInfo.goodsList.FirstOrDefault(m =>
						m.enumGoodsBelongsToType_Convert == bpGoodsItemInfo.enumGoodsBelongsToType
						&& m.GoodsPosition == bpGoodsItemInfo.GoodsPosition
						&& m.guid == bpGoodsItemInfo.guid);
					if (goodsInfo == null)
					{
						goodsInfo = new GoodsModel
						{
							BelongsTo = (int)bpGoodsItemInfo.enumGoodsBelongsToType,
							GoodsId = StringHelper.GetGuidStr(),
							GoodsItemId = bpGoodsItemInfo.GoodsItemId,
							GoodsPosition = bpGoodsItemInfo.GoodsPosition,
							guid = bpGoodsItemInfo.guid,
							Num = bpGoodsItemInfo.GoodsNum,
							PlayerId = session.minecraftSessionInfo.player.PlayerId,
							WastageValue = 100,
						};
						session.minecraftSessionInfo.goodsList.Add(goodsInfo);
					}
					else
					{
						goodsInfo.Num = bpGoodsItemInfo.GoodsNum;
					}

					furnitureCellGoodsInfo.Num -= canMoveCount;
					////同步更新源位置格子信息
					//var furnitureGoodsInfo = session.minecraftSessionInfo.goodsList.FirstOrDefault(m =>
					//	m.enumGoodsBelongsToType_Convert == furnitureCellGoodsInfo.enumGoodsBelongsToType
					//	&& m.GoodsPosition == furnitureCellGoodsInfo.GoodsPosition
					//	&& m.guid == furnitureCellGoodsInfo.guid
					//);
					//furnitureGoodsInfo.Num = furnitureCellGoodsInfo.Num;

					if (!positionOptList.Any(m => m.enumGoodsBelongsToType == bpGoodsItemInfo.enumGoodsBelongsToType && m.GoodsPosition == bpGoodsItemInfo.GoodsPosition && m.guid == bpGoodsItemInfo.guid))
					{
						positionOptList.Add(new BackpackGoodsPositionOpt()
						{
							enumGoodsBelongsToType = bpGoodsItemInfo.enumGoodsBelongsToType,
							GoodsPosition = bpGoodsItemInfo.GoodsPosition,
							guid = bpGoodsItemInfo.guid
						});
					}
					if (!positionOptList.Any(m => m.enumGoodsBelongsToType == furnitureCellGoodsInfo.enumGoodsBelongsToType_Convert && m.GoodsPosition == furnitureCellGoodsInfo.GoodsPosition && m.guid == furnitureCellGoodsInfo.guid))
					{
						positionOptList.Add(new BackpackGoodsPositionOpt()
						{
							enumGoodsBelongsToType = furnitureCellGoodsInfo.enumGoodsBelongsToType_Convert,
							GoodsPosition = furnitureCellGoodsInfo.GoodsPosition,
							guid = furnitureCellGoodsInfo.guid
						});
					}
					TakeGoods(session, defCommand, guid, enumGoodsBelongsToType, positionOptList, goodsModelList, out baseResp, posList);
				}
				else
				{
					//记录需要跳过的存储家具格子信息
					posList.Add(furnitureCellGoodsInfo.GoodsPosition);
				}
			}
			else
			{
				//家具没有物品了
			}
		}
	}
}
